﻿
using Xacml.Core;
using Xacml.Core.Interfaces;
using System.Collections;

namespace Xacml.Core.Runtime
{
  public class EvaluationValue : IFunctionParameter
  {
    private static EvaluationValue _true = new EvaluationValue((object) true, (IDataType) DataTypeDescriptor.Boolean);
    private static EvaluationValue _false = new EvaluationValue((object) false, (IDataType) DataTypeDescriptor.Boolean);
    private bool _isIndeterminate;
    private object _value;
    private IDataType _dataType;

    public static EvaluationValue True
    {
      get
      {
        return EvaluationValue._true;
      }
    }

    public static EvaluationValue False
    {
      get
      {
        return EvaluationValue._false;
      }
    }

    public static EvaluationValue Indeterminate
    {
      get
      {
        return new EvaluationValue(true);
      }
    }

    public object Value
    {
      get
      {
        return this._value;
      }
    }

    public bool IsIndeterminate
    {
      get
      {
        return this._isIndeterminate;
      }
    }

    public bool BoolValue
    {
      get
      {
        if (!(this._value is bool) || this._isIndeterminate)
          throw new EvaluationException("invalid data type.");
        return (bool) this._value;
      }
    }

    public bool IsBag
    {
      get
      {
        return this._value is BagValue;
      }
    }

    public int BagSize
    {
      get
      {
        return ((BagValue) this._value).BagSize;
      }
    }

    public ArrayList Elements
    {
      get
      {
        return ((BagValue) this._value).Elements;
      }
    }

    private EvaluationValue(bool isIndeterminate)
    {
      this._isIndeterminate = isIndeterminate;
    }

    public EvaluationValue(object value, IDataType dataType)
    {
      if (value is EvaluationValue)
      {
        this._value = ((EvaluationValue) value)._value;
        this._dataType = ((EvaluationValue) value)._dataType;
      }
      else if (value is BagValue)
      {
        this._value = value;
        this._dataType = dataType;
      }
      else if (value is IFunctionParameter)
      {
        this._value = ((IFunctionParameter) value).GetTypedValue(dataType, 0);
        this._dataType = dataType;
      }
      else
      {
        this._value = value;
        this._dataType = dataType;
      }
    }

    public IDataType GetType(EvaluationContext context)
    {
      return this._dataType;
    }

    public object GetTypedValue(IDataType dataType, int parNo)
    {
      if (dataType != this._dataType)
        throw new EvaluationException(Resource.ResourceManager[Resource.MessageKey.exc_type_mismatch, new object[2]
        {
          (object) dataType,
          (object) this._dataType
        }]);
      return this._value;
    }

    public IFunction GetFunction(int parNo)
    {
      throw new EvaluationException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_datatype_in_stringvalue, new object[2]
      {
        (object) parNo,
        (object) ""
      }]);
    }

    public override string ToString()
    {
      if (this.IsIndeterminate)
        return Decision.Indeterminate.ToString();
      if (this._value == null)
        return "null";
      return "[" + (object) this._dataType + ":" + this._value.ToString() + "]";
    }
  }
}
